package util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;


public class XMLToMathUtil {
	private static int flag = 0;// 0--transfering framework, 1--transfering
								// projects
	// tag���ڱ��CS(���ϵͳ)/CA(�����)/frame
	static String lastTag = "";
	static String tag = "";
	private StringBuffer sBuffer = new StringBuffer();

	public String getMathScriptFromXML(String fullXML) {
//		FileUtil.write("D://sdsa.txt", fullXML);
		flag = 0;
		// ����������XMLReader
		SAXParserFactory factory = SAXParserFactory.newInstance();
		factory.setValidating(false);// �ر�SAXParserFactory�����Ľ��������֤����
		SAXParser parser;
		XMLReader reader = null;
		try {
			parser = factory.newSAXParser();
			reader = parser.getXMLReader();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}

		reader.setContentHandler(new DefaultHandler() {
			public void startDocument() throws SAXException {
			}

			public void endDocument() throws SAXException {
			}

			public void startElement(String uri, String localName,
					String qualifiedName, Attributes attributes)
					throws SAXException {
				if (flag == 0) {// parse framework's start tag
					tag = qualifiedName.toUpperCase();
					String id = attributes.getValue("id");
					String path = attributes.getValue("path");
					String coordinate = attributes.getValue("coordinate");
					String field = attributes.getValue("field");
					String name = attributes.getValue("name");
					String stringToWrite = getStartCase(tag, id, path,
							coordinate, field, name);
					sBuffer.append(stringToWrite);
					lastTag = qualifiedName.toUpperCase();
				} else if (flag == 1) {// parse projects's start tag
					tag = qualifiedName.toUpperCase();
					String stringToWrite = getStartCase1(tag, attributes);
					sBuffer.append(stringToWrite);
					lastTag = qualifiedName.toUpperCase();
				}
			}

			public void endElement(String uri, String localName,
					String qualifiedName) throws SAXException {
				if (flag == 0) {// parse framework's end tag
					tag = qualifiedName.toUpperCase();
					String stringToWrite = getEndCase(tag);
					sBuffer.append(stringToWrite);
					lastTag = qualifiedName.toUpperCase();
				}

				else if (flag == 1) {// parse projects's end tag
					tag = qualifiedName.toUpperCase();
					String stringToWrite = getEndCase1(tag);
					sBuffer.append(stringToWrite);
					lastTag = qualifiedName.toUpperCase();
				}
			}

			public void characters(char[] ch, int start, int length) {
			}
		});
		try {
			reader.parse(new InputSource(new ByteArrayInputStream(fullXML
					.getBytes())));
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
		return sBuffer.toString();
	}

	// ��ϸ��Ƽ�path��/analysisdoc.doc
	// ���ڴ���framework's XML�Ŀ�ʼ���
	// case: "CS", "R0", {"R0"}, 1, "root", {"�����Ϊ����"},
	protected static String getStartCase(String tag, String id, String path,
			String coordinate, String field, String name) {
		if (path != null) {
			int pathLength = path.split(",").length;
			if (pathLength > 1) {
				String[] paths = path.split(",");
				path = "";
				for (int i = 0; i < pathLength - 1; i++) {
					path += "\"" + paths[i] + "\", ";
				}
				path += "\"" + paths[pathLength - 1] + "\"";
			} else
				path = "\"" + path + "\"";
		}
		if (tag.equals("ROOT"))
			return "";
		if (tag.equals("FRAMEWORK"))
			return "frm = ";
		String caseTemp = "\"" + tag + "\", " + "\"" + id + "\", " + "{" + path
				+ "}, " + " " + coordinate + ", " + "\"" + field + "\", ";
		if (tag.equals("CS")) {
			if (lastTag.equals("FRAMEWORK"))
				return "\n{\n" + caseTemp;
			if (lastTag.equals("DESCRIPTION"))
				return "\n{\n{\n" + caseTemp;
			if (lastTag.equals("CS"))
				return ",\n{\n" + caseTemp;
		}
		if (tag.equals("CA")) {
			if (lastTag.equals("DESCRIPTION"))
				return "\n{\n{\n" + caseTemp;
			if (lastTag.equals("CA"))
				return ",\n{\n" + caseTemp;
		}
		if (tag.equals("DESCRIPTION")) {
			return "{\"" + name + "\"},";
		}
		return "";
	}

	// ��ϸ��Ƽ�path��/analysisdoc.doc
	// ���ڴ���framework's XML�Ľ�����
	protected static String getEndCase(String tag) {
		if (tag.equals("ROOT"))
			return "";
		if (tag.equals("CS")) {
			if (lastTag.equals("DESCRIPTION"))
				return "{}\n}";
			if (lastTag.equals("CA"))
				return "\n}\n}";
		}
		if (tag.equals("CA")) {
			if (lastTag.equals("CS"))
				return "\n}\n}";
			if (lastTag.equals("DESCRIPTION"))
				return "{}\n}";
		}
		if (tag.equals("FRAMEWORK")) {
			// do some prepare work for parsing Projects
			flag = 1;
			lastTag = "";
			tag = "";
			return "";
		}
		if (tag.equals("DESCRIPTION"))
			return "";
		return "";
		// return "error in getEndCase, tag="+tag+", lastTag="+lastTag;
	}

	// ��ϸ��Ƽ�path��/analysisdoc.doc
	// ���ڴ���Projects' XML�Ŀ�ʼ���
	protected static String getStartCase1(String tag, Attributes attributes) {
		String name = null;
		String id = null;
		String cs = null;
		String ca = null;
		String coordinates = null;
		if (attributes.getValue("name") != null) {
			name = attributes.getValue("name");
		}
		if (attributes.getValue("id") != null) {
			id = attributes.getValue("id");
		}
		if (attributes.getValue("cs") != null) {
			cs = attributes.getValue("cs");
		}
		if (attributes.getValue("ca") != null) {
			ca = attributes.getValue("ca");
		}
		if (attributes.getValue("coordinates") != null) {
			coordinates = attributes.getValue("coordinates");
		}
		if (cs != null) {
			int pathLength = cs.split(",").length;
			if (pathLength > 1) {
				String[] paths = cs.split(",");
				cs = "";
				for (int i = 0; i < pathLength - 1; i++) {
					cs += "\"" + paths[i] + "\", ";
				}
				cs += "\"" + paths[pathLength - 1] + "\"";
			} else
				cs = "\"" + cs + "\"";
		}
		if (tag.equals("PROJECT"))
			return ";\n" + id + " =\n{\n\"" + name + "\",\"" + id + "\",";
		if (tag.equals("DESCRIPTION"))
			return "{\"" + name + "\"},";
		if (tag.equals("POINTSLIST"))
			return "\n{";
		if (tag.equals("POINTS")) {
			if (lastTag.equals("POINTSLIST"))
				return "\n{\n{" + cs + "},{" + ca + "},{";
			if (lastTag.equals("POINTS"))
				return ",\n{\n{" + cs + "},{" + ca + "},{";
		}
		if (tag.equals("POINT")) {
			if (lastTag.equals("POINTS"))
				return "{" + coordinates + "}";
		}
		if (tag.equals("POINT")) {
			if (lastTag.equals("POINT"))
				return ",{" + coordinates + "}";
		}
		return "";
	}

	// ��ϸ��Ƽ�path��/analysisdoc.doc
	// ���ڴ���Projects' XML�Ľ�����
	protected static String getEndCase1(String tag) {
		if (tag.equals("POINTS"))
			return "}\n}";
		if (tag.equals("POINTSLIST")) {
			return "\n}";
		}
		if (tag.equals("PROJECT"))
			return "\n}";
		if (tag.equals("PROJECTs")) {
			flag = 1;
			lastTag = "";
			tag = "";
			return "";
		}
		return "";
	}
	
	/**
	 * get whole mathematica's function scripts 
	 * @param methodList
	 * @param csPath
	 * @param proIds
	 * @param checkedAxises
	 * @param mathPackPath
	 * @return
	 */
	public String getMathScriptFromFuncs(List methodList, String csPath,
			String[] proIds, String[] checkedAxises, String mathPackPath) {
//		int methodSize = methodList.size();
//		if(methodSize<1)
//			return "error";
		StringBuffer ssBuffer = new StringBuffer();
//		String orderedAxises = getOrderedAxises(checkedAxises);
//		String proString = "";
//		if (proIds.length > 1)
//			proString = "{" + getStringFromStringArray(proIds) + "}";
//		else
//			proString = proIds[0];
//		// import mathematica package
//		String mathPath = getMathTypePath(mathPackPath);
//		if(methodSize==1) {
//			ssBuffer.append(";\nNeeds[\"DBA`\", (\"" + mathPath + "\")]\n");
//			ssBuffer.append(getFuncString(((MathMethod) methodList.get(0))
//					.getFuncName(), proString, csPath, orderedAxises));
//		}
//		else {
//			ssBuffer.append(";\nNeeds[\"DBA`\", (\"" + mathPath + "\")]\nGrid[{{");
//			for (int i = 0; i < methodList.size(); i++) {
//				if (i == 0) {
//					ssBuffer.append(getFuncString(((MathMethod) methodList.get(i))
//							.getFuncName(), proString, csPath, orderedAxises)+"}");
//				} else
//					ssBuffer.append(","
//							+ getFuncString("{"+((MathMethod) methodList.get(i))
//									.getFuncName(), proString, csPath,
//									orderedAxises)+"}");
//			}
//			ssBuffer.append("}]");
//		}
		return ssBuffer.toString();
	}
	
	/**
	 *	"/" change to "////"
	 * @param mathPackPath
	 * @return
	 */
	private String getMathTypePath(String mathPackPath) {
		return mathPackPath.replaceAll("\\\\", "\\\\\\\\\\\\\\\\");
	}
	
	/**
	 * get function method script
	 * @param funcName
	 * @param proString
	 * @param csPath
	 * @param orderedAxises
	 * @return
	 */
	private String getFuncString(String funcName, String proString,
			String csPath, String orderedAxises) {
		if (csPath != null) {
			int pathLength = csPath.split(",").length;
			if (pathLength > 1) {
				String[] paths = csPath.split(",");
				csPath = "";
				for (int i = 0; i < pathLength - 1; i++) {
					csPath += "\"" + paths[i] + "\", ";
				}
				csPath += "\"" + paths[pathLength - 1] + "\"";
			} else
				csPath = "\"" + csPath + "\"";
		}
		StringBuffer sb1 = new StringBuffer();
		if("SComboProjectsPlot2D".equals(funcName)) {
			sb1.append("\n" + funcName + "[frm, " + proString + ", {" + csPath
					+ "}, {" + orderedAxises + "}, 0.1]");
		}else{
			sb1.append("\n" + funcName + "[frm, " + proString + ", {" + csPath
					+ "}, {" + orderedAxises + "}]");
		}
			
		// if("SShowProjectPlot2D".equals(funcName) ||
		// "SShowProjectPlot3D".equals(funcName)||
		// "SComboProjectsBarChart3D".equals(funcName))
		// sb1.append("Color -> Red]");
		// else if("SShowProjectsPlot2D".equals(funcName) ||
		// "SShowProjectsPlot3D".equals(funcName))
		// sb1.append("Color -> {Yellow, Blue, Red}]");
		// else if("SComboProjectsPlot2D".equals(funcName))
		// sb1.append("0.1, ColorFunction -> Hue]");
		// else if("SComboProjectsPlot3D".equals(funcName))
		// sb1.append("ColorFunction -> \"BlueGreenYellow\"]");
		return sb1.toString();
	}
	
	/**
	 * change string[] to string
	 * @param stringArray
	 * @return
	 */
	private String getStringFromStringArray(String[] stringArray) {
		StringBuffer sb = new StringBuffer();
		int length = stringArray.length;
		for (int i = 0; i < length; i++) {
			sb.append("" + stringArray[i] + "");
			if (i == length - 1)
				return sb.toString();
			sb.append(",");
		}
		return null;
	}
	
	/**
	 * get the ordered axises, like [X,Y,Z] or [X,Y]
	 * @param checkedAxises
	 * @return
	 */
	private String getOrderedAxises(String[] checkedAxises) {
		String ss = "";
		boolean flag = false;
		if (checkedAxises.length == 2)
			flag = true;
		if (!flag) {
			ss = getIndexOfCertainCoord(checkedAxises, "X") + ","
					+ getIndexOfCertainCoord(checkedAxises, "Y") + ","
					+ getIndexOfCertainCoord(checkedAxises, "Z");
			return ss;
		}
		if (flag) {
			ss = getIndexOfCertainCoord(checkedAxises, "X") + ","
					+ getIndexOfCertainCoord(checkedAxises, "Y");
			return ss;
		}
		return null;
	}
	
	/**
	 * 
	 * @param checkedAxises
	 * @param ax
	 * @return [X's index, Y's index, (Z's index)]
	 */
	private int getIndexOfCertainCoord(String[] checkedAxises, String ax) {
		for (int i = 0; i < checkedAxises.length; i++) {
			if (checkedAxises[i].endsWith(ax))
				return i + 1;
		}
		return 0;
	}
}
